﻿<?
/**
 * 字符串加密、解密函数
 *
 *
 * @param   string  $txt        字符串
 * @param   string  $operation  ENCODE为加密，DECODE为解密，可选参数，默认为ENCODE，
 * @param   string  $key        密钥：数字、字母、下划线
 * @return  string
*/
function _authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
    $ckey_length = 4;

    $key = md5($key ? $key : 'acb64e13a4475e970b4976c4cf208946');
    $keya = md5(substr($key, 0, 16));
    $keyb = md5(substr($key, 16, 16));
       
    $keyc = $ckey_length ? ($operation == 'DECODE' ? 
        substr($string, 0, $ckey_length) : 
            substr(md5(microtime()), -$ckey_length)) : '';   

    $cryptkey = $keya.md5($keya.$keyc);   
    $key_length = strlen($cryptkey);   
    
    $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : 
        sprintf('%010d', $expiry ? $expiry + time() : 0) 
        . substr(md5($string.$keyb), 0, 16) . $string;   
    $string_length = strlen($string);
    $result = '';
    $box = range(0, 255);
    $rndkey = array();
    
    for($i = 0; $i <= 255; $i++) 
        $rndkey[$i] = ord($cryptkey[$i % $key_length]);   
    
    for($j = $i = 0; $i < 256; $i++) {   
        $j = ($j + $box[$i] + $rndkey[$i]) % 256;   
        $tmp = $box[$i];   
        $box[$i] = $box[$j];   
        $box[$j] = $tmp;   
    }   
    
    // 核心加解密部分   
    for($a = $j = $i = 0; $i < $string_length; $i++) {
        $a = ($a + 1) % 256;
        $j = ($j + $box[$a]) % 256;
        $tmp = $box[$a];
        $box[$a] = $box[$j];
        $box[$j] = $tmp;
        // 从密匙簿得出密匙进行异或，再转成字符
        $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
    }
    
    if($operation == 'DECODE') {
        if((substr($result, 0, 10) == 0 
            || substr($result, 0, 10) - time() > 0) 
            && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {   
            return substr($result, 26);
        } else {
            return '';
        }
    } else {
        return $keyc.str_replace('=', '', base64_encode($result));
    }
}
/**
* 通过随机字符串的MD5值和字符串的异或运算对字符串进行初步加密再通过密钥对初步加密过的字符串进一步通过异或运算加密
* @param string $txt 待加密的字符串
* @param string $key 密钥
* @return string 加密后的字符串
*/
function passport_encrypt($txt, $key) { 
srand((double)microtime() * 1000000); //播下随机种子 
$encrypt_key = md5(rand(0, 32000)); //生成随机数,并取得随机数的MD5值,做加密运算用.
$ctr = 0; //计数器
$tmp = ''; 
for($i = 0;$i < strlen($txt); $i++) {
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; //当计数器的值等于$encrypt_key的长度时,将计数器$ctr的长度设置为0;
$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]); //将$encrypt_key与字符串的每个字符进行异或运算
} 
return base64_encode(passport_key($tmp, $key)); 
}

/**
* 通过给定的密钥对加密的字符串解密
* @param string $txt 待解密的字符串
* @param string $key 密钥
* @param string 解密后的字符串
*/
function passport_decrypt($txt, $key) {
$txt = passport_key(base64_decode($txt), $key); //根据密钥对加密字符串进行初步解密
$tmp = ''; 
for($i = 0;$i < strlen($txt); $i++) { //把字符串中的随机数的MD5值中的每个字符取出来与加密字符串做异或运算进行解密
$md5 = $txt[$i]; 
$tmp .= $txt[++$i] ^ $md5; 
} 
return $tmp; 
}

/**
* 通过字符串和密钥异或运算的方式对字符串进行加密、解密
* @param string $txt 等待加密、或者解密的字符串
* @param string $encrypt_key 密钥
* @return string 返回加密、或解密过的字符串
*/
function passport_key($txt, $encrypt_key) {
$encrypt_key = md5($encrypt_key); //密钥md5加密
$ctr = 0; //计数器
$tmp = ''; 
for($i = 0; $i < strlen($txt); $i++){
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr; //计数器等于密钥md5值的长度时重新将计数器置为0
$tmp .= $txt[$i] ^ $encrypt_key[$ctr++]; 
} 
return $tmp; 
}